package com.icodingedu.springcloud.filter;

import com.icodingedu.springcloud.tools.BodyHackerFunction;
import com.icodingedu.springcloud.tools.BodyHackerHttpResponseDecorator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@Slf4j
@Component
public class ErrorFilter implements GatewayFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //获取请求request路径数据
        ServerHttpRequest request = exchange.getRequest();
        BodyHackerFunction delegate = (resp,body) -> Flux.from(body)
                    .flatMap(orgBody -> {
                        //原始的response body
                        byte[] orgContent = new byte[orgBody.readableByteCount()];
                        orgBody.read(orgContent);

                        String content = new String(orgContent);
                        log.info("originall content{}",content);

                        //如果是500,则替换
                        if(resp.getStatusCode().value()==500){
                            content = String.format("{\"status\":%d,\"path\":\"%s\"}",
                                    resp.getStatusCode().value(),
                                    request.getPath().value());
                        }
                        //告知客户端body的长度，如果不设置客户端会一致等待
                        HttpHeaders headers = resp.getHeaders();
                        headers.setContentLength(content.length());
                        return resp.writeWith(Flux.just(content)
                            .map(bx -> resp.bufferFactory().wrap(bx.getBytes())));
                    }).then();
        //将装饰器当作Response返回
        BodyHackerHttpResponseDecorator responseDecorator = new BodyHackerHttpResponseDecorator(delegate,exchange.getResponse());

        return chain.filter(exchange.mutate().response(responseDecorator).build());
    }

    @Override
    public int getOrder() {
        //WRITE_RESPONSE_FILTER执行顺序是-1
        return -2;
    }
}
